Make an1 layer type sticky to enable better merges, document 'type' option, add road...
authorparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 30 Aug 2005 15:57:51 +0000 (15:57 +0000)
committerparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 30 Aug 2005 15:57:51 +0000 (15:57 +0000)
gpsbabel/README
gpsbabel/an1.c

index a1145174283099483ef1509c13f0b3ddc592b17a..8960eefda3ead2a452ca856a0d6324e506c210c5 100644 (file)
@@ -906,13 +906,30 @@ THE FORMATS
         In this case, the merged data will contain all of the properties
         of the original data.
 
-        Currently, GPSBabel only writes drawing layers, as opposed to road, 
-        track, and other specialized layers.  If your input file is a road, 
-        track, trail, or waypoint layer, you should not attempt to write to 
-        an .an1 file as the results may be unpredictable.  Note that this 
-        also applies to merging files, so you can't currently merge two road
-        layers with GPSBabel (officially; there is an unsupported "type" 
-        option that works in limited cases.)
+        GPSBabel has limited experimental support for other types of layers
+        besides the default "drawing" layer with the use of two options:
+
+        The "type" option specifies the type of the drawing layer to be 
+        created.  The supported values are "drawing", "road", "trail", 
+        "waypoint", or "track".  If you do not specify a type, the default
+        will be either the type of the previous an1 file or "drawing" if 
+        there is no previous file.  This lets you merge, for example, two
+        road layers without having to specify "type=road" for the output.
+
+        If you are creating a road layer, you may also use the "road" option,
+        which allows you to change the types of roads based on their names.
+        You can change multiple roads at the same time.  Currently supported
+        types are "limited", "toll", "us", "state", "major", and "local".
+        This option has a special format that is best demonstrated by example:
+
+        "type=limited|I-599|major|Beecher St." 
+
+        This option will cause any road named "I-599" to become a limited- 
+        access highway and any road named "Beecher St." to become a major
+        connector.  Note that roads that have had their types changed in 
+        this way might not be editable in Street Atlas, so make sure they
+        are where you want them before you change them, and make sure to keep
+        a backup of your original road layer.
 
     TomTom
 
index 1c8983fd9f2fa769920461314600ea9eb89e94e7..0c3e3ff0addb8d43f959bb83e49ce8523e7b5961 100644 (file)
@@ -30,15 +30,27 @@ FILE *infile;
 FILE *outfile;
 
 static char *output_type = NULL;
-long output_type_num = 0;
+static char *road_changes = NULL;
+short output_type_num = 0;
+
+short last_read_type = 0;
 
 static long serial=10000;
 static long rtserial=1;
 
+typedef struct roadchange {
+       long type;
+       char *name;
+} roadchange;
+
+roadchange *roadchanges = NULL;
+
 static
 arglist_t an1_args[] = {
-       {"type", &output_type, "Type of .an1 file (0=drawing)", 
-               "0", ARGTYPE_HIDDEN | ARGTYPE_INT },
+       {"type", &output_type, "Type of .an1 file (see README)", 
+               "", ARGTYPE_STRING },
+       {"road", &road_changes, "Road type changes (see README)",
+               "", ARGTYPE_HIDDEN | ARGTYPE_STRING },
        {0, 0, 0, 0 }
 };
 
@@ -236,8 +248,7 @@ typedef struct {
 
 typedef struct {
        format_specific_data fs;
-       short magic;
-       short unk1;
+       long roadtype;
        short serial;
        long unk2;
        short unk3;
@@ -426,8 +437,7 @@ static void Read_AN1_Line( FILE *f, an1_line_record *line ) {
        
        short len;
        
-       line->magic = ReadShort( f );
-       line->unk1 = ReadShort( f );
+       line->roadtype = ReadLong( f );
        line->serial = ReadShort( f );
        line->unk2 = ReadLong( f );
        line->unk3 = ReadShort( f );
@@ -449,8 +459,7 @@ static void Read_AN1_Line( FILE *f, an1_line_record *line ) {
 static void Write_AN1_Line( FILE *f, an1_line_record *line ) {
        short len;
        
-       WriteShort( f, line->magic );
-       WriteShort( f, line->unk1 );
+       WriteLong( f, line->roadtype );
        WriteShort( f, line->serial );
        WriteLong( f, line->unk2 );
        WriteShort( f, line->unk3 );
@@ -511,11 +520,13 @@ static void Read_AN1_Header( FILE *f ) {
        
        magic = ReadShort( f );
        type = ReadShort( f );
+       
+       last_read_type = type;
 }
 
 static void Write_AN1_Header( FILE *f ) {
        WriteShort( f, 11557 );
-       WriteShort( f, (short) atoi( output_type ) );
+       WriteShort( f, output_type_num );
 }
 
 static void Read_AN1_Bitmaps( FILE *f ) {
@@ -659,6 +670,27 @@ static void Read_AN1_Lines( FILE *f ) {
        }
 }
 
+static void
+Make_Road_Changes( an1_line_record *rec ) {
+       int i = 0;
+       
+       if ( !rec ) {
+               return;
+       }
+       
+       if ( !roadchanges ) {
+               return;
+       }
+       
+       while ( roadchanges[i].name ) {
+               if ( !case_ignore_strcmp(roadchanges[i].name, rec->name )) {
+                       rec->roadtype = roadchanges[i].type;
+                       break;
+               }
+               i++;
+       }
+}
+       
 static void
 Write_One_AN1_Line( const route_head *rte )
 {
@@ -677,12 +709,12 @@ Write_One_AN1_Line( const route_head *rte )
                                        rec = Alloc_AN1_Line();
                                        memcpy( rec, fs, sizeof(an1_line_record));
                                        local = 1;
-                                       rec->magic = 4112;
-                                       rec->unk1 = 4359;
+                                       rec->roadtype = 0x11100541;
                                        rec->unk2 = 655360;
                                        rec->type = 14;
                                        rec->unk8 = 2;
                                } // end if
+                               Make_Road_Changes( rec );
                                break;
                        case 2:
                                if ( rec->type != 15 ) {
@@ -705,27 +737,26 @@ Write_One_AN1_Line( const route_head *rte )
        else {
                rec = Alloc_AN1_Line();
                local = 1;
+               rec->name = NULL;
                switch (output_type_num) {
                        /*  drawing road trail waypoint track  */
                        case 1: /* road */
-                               rec->magic = 4112;
-                               rec->unk1 = 4359;
+                               rec->roadtype = 0x11100541;
                                rec->unk2 = 655360;
                                rec->type = 14;
                                rec->unk8 = 2;
+                               rec->name = xstrdup( rte->rte_name ); 
                                break;
                                
                        case 2: /* trail */
-                               rec->magic = 7248;
-                               rec->unk1 = 4359;
+                               rec->roadtype = 0x11071c50;
                                rec->unk2 = 917504;
                                rec->type = 15;
                                rec->unk8 = 2;
                                break;
                                
                        case 4: /* track */
-                               rec->magic = 21;
-                               rec->unk1 = 18560;
+                               rec->roadtype = 0x48800015;
                                rec->unk2 = 917504;
                                rec->type = 16;
                                rec->unk4 = 2;
@@ -735,8 +766,7 @@ Write_One_AN1_Line( const route_head *rte )
                        case 0: /* drawing */
                        case 3: /* waypoint - shouldn't have lines */
                        default:
-                               rec->magic = 21;
-                               rec->unk1 = 18560;
+                               rec->roadtype = 0x48800015;
                                rec->unk2 = 1048576;
                                rec->type = 2;
                                rec->unk4 = 2;
@@ -746,7 +776,9 @@ Write_One_AN1_Line( const route_head *rte )
                                rec->unk8 = 2;
                                break;
                }
-               rec->name = xstrdup( "" );
+               if ( !rec->name ) {
+                       rec->name = xstrdup( "" );
+               }
                                
        }
        rec->serial = serial++;
@@ -792,11 +824,133 @@ static void Write_AN1_Lines( FILE *f ) {
        track_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex );
 }
 
+static void
+Init_Output_Type( void )
+{
+       if ( !output_type || !output_type[0]) {
+               output_type_num = last_read_type;
+               return;
+       }
+       if ( (output_type[0] & 0xf0 ) == 0x30) {
+               output_type_num = atoi( output_type );
+       }
+       else {
+               output_type_num = 0;
+               if ( !case_ignore_strcmp(output_type, "drawing")) {
+                       output_type_num = 0;
+               }
+               else if ( !case_ignore_strcmp(output_type, "road")) {
+                       output_type_num = 1;
+               }
+               else if ( !case_ignore_strcmp(output_type, "trail")) {
+                       output_type_num = 2;
+               }
+               else if ( !case_ignore_strcmp(output_type, "waypoint")) {
+                       output_type_num = 3;
+               }
+               else if ( !case_ignore_strcmp(output_type, "track")) {
+                       output_type_num = 4;
+               }
+               else {
+                       fatal(MYNAME ": type must be "
+                           "drawing, road, trail, waypoint, or track\n");
+               }       
+       }
+       last_read_type = output_type_num;
+}
+
+static long 
+Parse_Change_Type( char *type ) {
+       long retval = 0x11100541;
+       
+       if ( !case_ignore_strcmp( type, "limited" )) {
+               retval = 0x11070430;
+       }
+       else if ( !case_ignore_strcmp( type, "toll" )) {
+               retval = 0x11070470;
+       }
+       else if ( !case_ignore_strcmp( type, "us" )) {
+               retval = 0x11070870;
+       }
+       else if ( !case_ignore_strcmp( type, "state" )) {
+               retval = 0x11070c10;
+       }
+       else if ( !case_ignore_strcmp( type, "major" )) {
+               retval = 0x11070c30;
+       }
+       else {
+               fatal( MYNAME ": unknown road type for road changes\n" );
+       }
+       return retval;
+}
+
+static void 
+Free_Road_Changes( void )
+{
+       int i = 0;
+       if ( roadchanges ) {
+               while ( roadchanges[i].name ) {
+                       xfree(roadchanges[i].name );
+                       i++;
+               }
+               xfree( roadchanges );
+       }
+       roadchanges = NULL;
+}              
+
+static void
+Init_Road_Changes( void )
+{
+       int count = 0;
+       char *strType = NULL;
+       char *name = NULL;
+       char *bar = NULL;
+       char *copy = NULL;
+       Free_Road_Changes();
+       
+       if ( !road_changes || !road_changes[0] ) {
+               return;
+       }
+       bar = strchr( road_changes, '|' );
+       while ( bar ) {
+               count++;
+               bar = strchr( bar+1, '|' );
+       }
+       if ( !(count&1)) {
+               fatal( MYNAME ": invalid format for road changes\n" );
+       }
+       count = 1 + count / 2;
+       roadchanges = (roadchange *)xmalloc( (count+1) * sizeof(roadchange));
+       
+       roadchanges[count].type = 0;
+       roadchanges[count].name = NULL;
+       
+       copy = xstrdup( road_changes );
+       bar = copy;
+       
+        while ( count ) {
+               count--;
+               name = bar;
+               bar = strchr( name, '|' );
+               *bar = '\0';
+               bar++;
+               strType = bar;
+               bar = strchr( strType, '|' );
+               if ( bar ) {
+                       *bar = '\0';
+                       bar++;
+               }       
+               roadchanges[count].name = xstrdup( name );
+               roadchanges[count].type = Parse_Change_Type( strType ); 
+       }               
+       
+       xfree( copy );
+}
+
 static void
 rd_init(const char *fname)
 {
        infile = xfopen(fname, "rb", MYNAME);
-       output_type_num = atoi( output_type );
 }
 
 static void
@@ -818,12 +972,14 @@ static void
 wr_init(const char *fname)
 {
        outfile = xfopen( fname, "wb", MYNAME );
-       output_type_num = atoi( output_type );
+       Init_Output_Type();
+       Init_Road_Changes();
 }
 
 static void
 wr_deinit( void ) 
 {
+       Free_Road_Changes();
        fclose(outfile);
 }